﻿
namespace HSS.ComponentModel
{
	#region Using Directives
	using System;
	using System.ComponentModel;
	using System.Linq.Expressions;
	#endregion

	#region PropertyChangedExtensions
	/// <summary>
	/// Extension class for assisting with INotifyPropertyChanged.
	/// </summary>
	public static class PropertyChangedExtensions
	{
		/// <summary>
		/// Calls the provided <see cref="PropertyChangingEventHandler"/> 
		/// (if it's not null) providing the sender and name of the property
		/// as evaluated from the expression.
		/// </summary>
		/// <typeparam name="T">The Type of the Property.</typeparam>
		/// <param name="handler">The <see cref="PropertyChangingEventHandler"/> to call.</param>
		/// <param name="expression">The expression to process.</param>
		/// <exception cref="ArgumentException">The expression must select a property type.</exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
		public static void NotifyPropertyChanging<T>(this PropertyChangingEventHandler handler, Expression<Func<T>> expression)
		{
			if (handler != null)
			{
				var memberExpression = expression.GetPropertyExpression<T>();
				if (memberExpression != null)
				{
					var sender = ((ConstantExpression)memberExpression.Expression).Value;
					handler(sender, new PropertyChangingEventArgs(memberExpression.Member.Name));
				}
			}
		}
		/// <summary>
		/// Calls the provided <see cref="PropertyChangedEventHandler"/> 
		/// (if it's not null) providing the sender and name of the property
		/// as evaluated from the expression.
		/// </summary>
		/// <typeparam name="T">The Type of the Property.</typeparam>
		/// <param name="handler">The <see cref="PropertyChangedEventHandler"/> to call.</param>
		/// <param name="expression">The expression to process.</param>
		/// <exception cref="ArgumentException">The expression must select a property type.</exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
		public static void NotifyPropertyChanged<T>(this PropertyChangedEventHandler handler, Expression<Func<T>> expression)
		{
			if (handler != null)
			{
				var property = expression.GetPropertyExpression<T>();
				if (property != null)
				{
					var sender = ((ConstantExpression)property.Expression).Value;
					handler(sender, new PropertyChangedEventArgs(property.Member.Name));
				}
			}
		}
		/// <summary>
		/// Calls the provided <see cref="Action{string}"/> providing the name of the property
		/// as evaluated from the expression.
		/// </summary>
		/// <typeparam name="T">The Type of the Property.</typeparam>
		/// <param name="notifier">The <see cref="Action{string}"/> to call.</param>
		/// <param name="expression">The expression to process.</param>
		/// <exception cref="ArgumentException">The expression must select a property type.</exception>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "notifier"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
		public static void NotifyPropertyAction<T>(this Action<string> notifier, Expression<Func<T>> expression)
		{
			if (notifier != null)
				notifier(expression.GetPropertyName<T>());
		}
	}
	#endregion
}